#ifndef UNITS_H
#define UNITS_H



#include "players.h"
#include "game.h"
#include <queue>
#include <map>
#include <string>



using std::string;



class unit;
class player;



class object
{
	

public:

	object( int x, int y, string nm )
	{	
		pos_x = x;
		pos_y = y;
		name = nm;
	};
	virtual unsigned int get_x() { return pos_x; };
	virtual unsigned int get_y() { return pos_y; };
	virtual void set_pos( unsigned int x, unsigned int y ) { pos_x = x; pos_y = y; };
	virtual int get_type() { return type; };
	virtual string get_name() { return name; };
	virtual object* clone() = 0;

	template< class This >
	This* clonetpl()
	{
		return new This( *static_cast< This* >( this ) );
	};


protected:

	unsigned int pos_x;
	unsigned int pos_y;
	int type;
	string name;

};



class bonus: public object
{

public:

	bonus( unsigned int x, unsigned int y, string nm ): object( x, y, nm )
	{
		type = 0;
	};	

	void init( unsigned int x, unsigned int y )
	{
		pos_x = x;
		pos_y = y;
	};

	virtual void effect( unit* u ) = 0;

};



class firstaidkit: public bonus
{

public:

	firstaidkit( unsigned int x, unsigned int y, string nm ): bonus( x, y, nm ) {};

	void effect( unit* u );

	virtual object* clone()
	{
		return clonetpl< firstaidkit >();
	};

};



class unit: public object
{

public:

	unit( unsigned int x, unsigned int y, player* p, int n, unsigned int pr, unsigned int ra, unsigned int he, unsigned int sh, unsigned int we, unsigned int cm, unsigned int cf, string nm ): object ( x, y, nm )
	{
		pl = p;
		nbr = n;
		type = 1;
		price = pr;
		range = ra;
		health = he;
		shield = sh;
		weapon = we;
		cost_move = cm;
		cost_fire = cf;	
	};

	void init( unsigned int x, unsigned int y, player* p, int n )
	{
		pos_x = x;
		pos_y = y;
		pl = p;
		nbr = n;
	};

	bool move( unsigned int x, unsigned int y );
	bool fire( unsigned int x, unsigned int y );
	bool move_handle( std::queue< std::pair< unsigned int, unsigned int > >* path, unsigned int x, unsigned int y );
	bool fire_handle( unsigned int x, unsigned int y );
	unsigned int get_cost_move() { return cost_move; };
	unsigned int get_cost_fire() { return cost_fire; };
	unsigned int get_price() { return price; };
	unsigned int get_range() { return range; };
	int get_health() { return health; };
	unsigned int get_shield() { return shield; };
	unsigned int get_weapon() { return weapon; };
	void set_health( unsigned int h ) { health = h; };
	string get_info();
	void hit( unsigned int w );
	player* get_player() { return pl; };
	void set_player( player* p ) { pl = p; };
	int get_type() { return type; };
	int get_nbr() { return nbr; };
	int get_id();

	virtual object* clone()
	{
		return clonetpl< unit >();
	};


protected:

	player* pl;
	unsigned int price;
	unsigned int range;
	int health;
	unsigned int shield;
	unsigned int weapon;
	unsigned int cost_move;
	unsigned int cost_fire;	
	int nbr;

};



class prototypes
{

public:

	static prototypes* get_instance();

	void set_new_unit( std::string nm, unsigned int pr, unsigned int ra, unsigned int he, unsigned int sh, unsigned int we, unsigned int cm, unsigned int cf )
	{
		units[ nm ] = new unit( 0, 0, 0, 0, pr, ra, he, sh, we, cm, cf, nm );
	};

	std::map< string, unit* > units;
	std::map< string, bonus* > bonuses;


	int x;


private:

	prototypes( int _x ): x( _x )
	{
		bonuses[ "First aid kit" ] = new firstaidkit( 0, 0, "First aid kit" );
	};
	prototypes( const prototypes& );
	prototypes& operator=( const prototypes& x );

};



#endif